package com.apobates.forum.toro.proxy;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Supplier;

/**
 * 聚合属性构建器
 * 适用于: 构造的对象(target.OrdersVo)继承自查询对象(select.Orders)
 * @param <E> 最终结果的类型
 *
 * @author xiaofanku@live.cn
 * @since 20220517
 */
public class ProxyMapper<E> {
    private static final Logger logger = LoggerFactory.getLogger(ProxyMapper.class);
    /**
     * 目标对象Class
     * 例: OrdersVo.class
     */
    private final Class<E> className;

    /**
     * ProxyMapper构造函数
     *
     * @param className 目标对象Class. 例: OrdersVo.class
     */
    private ProxyMapper(Class<E> className) {
        this.className = className;
    }

    /**
     * 设置代理的目标对象Class. 通常是查询对象的子类
     *
     * @param className 目标对象Class. 例: OrdersVo.class
     * @return 聚合属性构建器
     * @param <E> 目标对象类型
     */
    public static <E> ProxyMapper proxy(Class<E> className) {
        return new ProxyMapper(className);
    }

    /**
     * 一对一模式(one to one)
     * 例: 一张订单的购买者和商品的聚合
     * 适用于: 已知起始对象实例
     *
     * @param selectObj 查询对象实例. 例: Orders
     * @param isConcurrent 是否并发执行;true并发,false串行
     * @return 聚合属性执行器
     * @param <T> 基对象的类型
     */
    public <T> ProxyMapperExecutor<E,T> by(T selectObj, boolean isConcurrent) {
        final Collection<T> args = Collections.unmodifiableList(List.of(selectObj));
        return new ProxyMapperExecutor(()->args, this.className, isConcurrent, false);
    }

    /**
     * 一对一模式(one to one)
     * 例: 一张订单的购买者和商品的聚合
     * 适用于: 起始对象实例不确定时
     *
     * @param selectObjSup 起始对象供应函.
     * @param isConcurrent 是否并发执行;true并发,false串行.
     * @return
     * @param <T>
     * @param <A>
     */
    public <T,A> ProxyMapperExecutor<E,T> supplyOne(Supplier<T> selectObjSup, boolean isConcurrent) {
        final Collection<T> args = Collections.unmodifiableList(List.of(selectObjSup.get()));
        return new ProxyMapperExecutor(()->args, this.className, isConcurrent, false);
    }

    /**
     * 多对多模式(many to many)
     * 例: 不同人购买不同商品的订单聚合
     * 适用于: 已知起始对象实例
     *
     * @param selectObjSet 查询对象实例集合. 例: Set<Orders>
     * @param isConcurrent 是否并发执行;true并发,false串行.
     * @return 聚合属性执行器
     * @param <T> 基对象的类型
     */
    public <T> ProxyMapperExecutor<E,Collection<T>> by(Collection<T> selectObjSet, boolean isConcurrent){
        final Collection<T> args = Collections.unmodifiableCollection(selectObjSet);
        return new ProxyMapperExecutor(()->args, this.className, isConcurrent, true);
    }

    /**
     * 多对多模式(many to many)
     * 例: 不同人购买不同商品的订单聚合
     * 适用于: 起始对象实例不确定时
     *
     * @param selectObjSetSup 起始对象供应函.
     * @param isConcurrent 是否并发执行;true并发,false串行.
     * @return 聚合属性执行器
     * @param <T> 基对象的类型
     */
    public <T> ProxyMapperExecutor<E,Collection<T>> supplyMany(Supplier<Collection<T>> selectObjSetSup, boolean isConcurrent){
        return new ProxyMapperExecutor(selectObjSetSup, this.className, isConcurrent, true);
    }

    /**
     * 返回基础属性语句
     * @return
     */
    public MapperAttrStatements one() {
        return new MapperAttrStatements();
    }

    /**
     * 返回批量属性语句
     * @return
     */
    public MapperMultiAttrStatements many() {
        return new MapperMultiAttrStatements();
    }
}
